#ifndef _GONGFU_PANDA_DEFINES_H_
#define _GONGFU_PANDA_DEFINES_H_
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <pthread.h>
#include <event.h>
#include <iostream>
#include <sys/socket.h>
#include <sys/un.h>
#include <signal.h>
#include <sys/resource.h>
#include <sys/uio.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>

///////////////

//#define    ANT_CONN_ERR_CLOSE           -9999
//#define    ANT_CONN_NO_REPLY            -9998


static const int  ANT_CONN_ERR_CLOSE     =  -9999;
static const int  ANT_CONN_NO_REPLY      =  -9998;

//////////////
static const int  TRANSMIT_COMPLETE      =  0;
static const int  TRANSMIT_INCOMPLETE    =  1;
static const int  TRANSMIT_SOFT_ERROR    =  2;
static const int  TRANSMIT_HARD_ERROR    =  3;


static const int  DATA_BUFFER_SIZE       =  2048;
//static const int  UDP_READ_BUFFER_SIZE     65536
//static const int  UDP_MAX_PAYLOAD_SIZE     1400
//#define UDP_HEADER_SIZE          8
static const int  MAX_SENDBUF_SIZE       =   (32 * 1024 * 1024);
static const int  ITEMS_PER_ALLOC        =   64;
static const int  NANTX_HEADER_LEN       =  4;
static const int  NANTX_HEADER_LENGTH    =  7;
static const int  READ_BUFFER_HIGHWAT    =  8192;


#define SOCKET_MTU_HEADER_SIZE       52
#define NANTX_EVENT_TIMER            "t"
#define NANTX_HEADER1                "x"
#define NANTX_HEADER2                "yz"


//typedef unsigned int rel_time_t;
/* An item in the connection queue. */
typedef struct conn_queue_item CQ_ITEM;
struct conn_queue_item {
    int     sfd;
    int     init_state;
    int     event_flags;
    int     read_buffer_size;
    int     is_udp;
    CQ_ITEM *next;
};

/* A connection queue. */
typedef struct conn_queue CQ;
struct conn_queue {
    CQ_ITEM *head;
    CQ_ITEM *tail;
    pthread_mutex_t lock;
    pthread_cond_t  cond;
};

typedef struct {
    pthread_t thread_id;        /* unique ID of this thread */
    struct event_base *base;    /* libevent handle this thread uses */
    struct event notify_event;  /* listen event for notify pipe */
    int notify_receive_fd;      /* receiving end of notify pipe */
    int notify_send_fd;         /* sending end of notify pipe */
    CQ  new_conn_queue;         /* queue of new connections to handle */
} LIBEVENT_THREAD;


struct settings {
    size_t maxbytes;
    int maxconns;
    int port;
    char *inter;
    int verbose;
    char *socketpath;   /* path to unix socket if using local socket */
    int access;  /* access mask (a la chmod) for unix domain socket */
    int num_threads;        /* number of libevent threads to run */
};

enum conn_states {
    conn_listening,  /** the socket which listens for connections */
    conn_read,       /** reading in a command line */
    conn_write,      /** writing out a simple response */
    conn_nread,      /** reading in a fixed number of bytes */
    conn_swallow,    /** swallowing unnecessary bytes w/o storing */
    conn_closing,    /** closing this connection */
    conn_mwrite,     /** writing out many items sequentially */
};

typedef struct conn conn;
struct conn {
    int    sfd;
    int    state;
    struct event event;
    short  ev_flags;
    short  which;   /** which events were just triggered */

    char   *rbuf;   /** buffer to read commands into */
    char   *rcurr;  /** but if we parsed some already, this is where we stopped */
    unsigned int    rsize;   /** total allocated size of rbuf */
    unsigned int    rbytes;  /** how much data, starting from rcur, do we have unparsed */

    char   *wbuf;
    char   *wcurr;
    unsigned int   wsize;
    unsigned int   wbytes;
    int    write_and_go; /** which state to go into after finishing current write */
    void   *write_and_free; /** free this memory after finishing writing */

    struct sockaddr request_addr; /* Who sent the most recent request */
    socklen_t request_addr_size;

    bool   noreply;   /* True if the reply should not be sent. */
    conn   *next;     /* Used for generating a list of conn structures */
    char cIP[ INET6_ADDRSTRLEN + 1 ];
};


#endif // _GONGFU_PANDA_DEFINES_H_
